#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "../include/transportADT.h"
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

static void idToString(int id, char * buff);

struct transportCDT{
	int id_fifo;		//file descriptor del fifo
	int id;				//id del proceso y creador del fifo
	int sendid;			//id del proceso al cual se quiere enviar un mensaje
};

transportADT
openTrans(void * id){
	char aux[MSG_LEN+1];
	int fd;
	struct transportCDT * trans;

	idToString(*((int *)id), aux);
	//el fifo se crea con el en id pasado a string
	if(mkfifo(aux, 0666)==-1) {
		return NULL;
	}
	//abro para lectura y escritura para que no quede bloqueado el fifo esperado
	if((fd=open(aux, O_RDWR))<0) {
		return NULL;
	}
	if((trans=malloc(sizeof(struct transportCDT)))==NULL) {
		exit(1);
	}
	trans->id_fifo=fd;
	trans->id=trans->sendid=*((int *)id);

	return trans;
}

transportADT
getTrans(void * id, void * dest) {
	struct transportCDT * trans;

	if((trans=openTrans(id))!=NULL)
		trans->sendid=*((int *)dest);

	return trans;
}

/*
 * 	-1 error de lectura
 */
int
writeMsg(transportADT trans, const void * buf, int size){
	char buffaux[MSG_LEN+1+sizeof(int)];
	char nameaux[MSG_LEN+1];
	int fd, cont=0, aux;

	if (size>MSG_LEN)
		return -1;

	memcpy(buffaux, &(trans->id), sizeof(int));
	memcpy(buffaux+sizeof(int), (char *)buf, size);
	idToString(trans->sendid, nameaux);
	//abro el fifo al cual se le quiere escribir solo para escribir
	fd = open(nameaux, O_WRONLY);

	while(cont!= MSG_LEN+1+sizeof(int))
		if((aux=write(fd, buffaux, MSG_LEN+1+sizeof(int))) == -1)
			return -1;
		else
			cont+=aux;

	//luego de escrito el mensaje cierro el fifo al cual me comunique
	close(fd);

	return size;
}

/*
 * 	-1 error de lectura
 */
int
readMsg(transportADT trans, void * buf, int size){
	char buffaux[MSG_LEN+1+sizeof(int)];
	int aux, cont=0;

	while(cont!=MSG_LEN+1+sizeof(int))
		if((aux=read(trans->id_fifo, buffaux, MSG_LEN+1+sizeof(int)))<0)
			return -1;
		else
			cont+=aux;
	memcpy(&trans->sendid, buffaux, sizeof(int));
	memcpy((char *)buf, buffaux+sizeof(int), size);

	return size;
}

void
closeTrans(transportADT trans){
	char buff[MSG_LEN+1];

	if(trans!=NULL) {
		//cierro el fifo
		close(trans->id_fifo);
		idToString(trans->id, buff);
		//elimino el fifo
		unlink(buff);
		free(trans);
	}
}

static void
idToString(int id, char * buff) {
	int i, j;
	char aux[MSG_LEN+1];

	buff[0]='/';
	buff[1]='t';
	buff[2]='m';
	buff[3]='p';
	buff[4]='/';
	for(i=0; id; ++i) {
		aux[i]=id%10+'0';
		id=id/10;
	}
	for(j=5; i; --i, ++j)
		buff[j]=aux[i-1];
	buff[j]='\0';
}
